<?php
namespace Maowenke\PersonalWechatSdk;
use Maowenke\PersonalWechatSdk\app\WecateApp;
use Maowenke\PersonalWechatSdk\applet\WecateApplet;

class Wecate
{
    protected $config = [
        'sign_type'=>'MD5',
        'trade_type'=>'APP',
    ];
    protected $message = '';
    protected $curl = '';

    /**
     * Wecate constructor.
     * @param array $config
     */
    public function __construct(array $config=[]){
        if(!empty($config)){
            foreach ($config as $key=>$value){
                $this->config[strtolower($key)] = $value;
            }
//            $this->config = $config;
        }
        $this->curl = new Curl($config);
    }

    /**设置配置信息
     * @param array $config
     */
    public function setConfig(array $config=[]){
        if(!empty($config)){
            foreach ($config as $key=>$value){
                $this->config[strtolower($key)] = $value;
            }
//            $this->config = $config;
        }
        return $this;
    }

    /**获取配置
     * @return array
     */
    public function getCofnig(string $str=''){
        if(empty($str)){
            return $this->config;
        }else{
            $str = strtolower($str);
            if($str=='appid'||$str=='app_id'){
                return $this->config['appid']??$this->config['app_id'];
            }else{
                return $this->config[$str];
            }
        }
    }

    /**验证数据
     * @return bool
     */
    public function verification($str='appid',$return=true){
        if($str=='appid'||$str=='app_id'){
            if(!isset($this->config['appid'])&&!isset($this->config['app_id'])){
                if($return){
                    $this->message = '请设置appid';
                    return false;
                }else{
                    throw new \Exception('请设置appid');
                }
            }
            if(empty($this->config['appid'])&&empty($this->config['app_id'])){
                if($return){
                    $this->message = 'appid不能为空';
                    return false;
                }else{
                    throw new \Exception('appid不能为空');
                }
            }
        }elseif($str=='secret'){
            if(!isset($this->config['secret'])&&!isset($this->config['secret'])){
                if($return){
                    $this->message = '请设置secret';
                    return false;
                }else{
                    throw new \Exception('请设置secret');
                }
            }
            if(empty($this->config['secret'])&&empty($this->config['secret'])){
                if($return){
                    $this->message = 'secret不能为空';
                    return false;
                }else{
                    throw new \Exception('secret不能为空');
                }
            }
        }else{
            if(is_array($str)){
                foreach ($str as $value){
                    if(empty($this->config[$value])){
                        if($return){
                            $this->message =  $value.'不能为空';
                            return false;
                        }else{
                            throw new \Exception( $value.'不能为空');
                        }
                    }
                }
            }else{
                if(empty($this->config[$str])){
                    if($return){
                        $this->message = $str.'不能为空';
                        return false;
                    }else{
                        throw new \Exception($str.'不能为空');
                    }
                }
            }
        }
        return true;
    }

    /**检查数据
     * @param array $key
     * @param array $data
     * @param $return
     * @return bool
     * @throws \Exception
     */
    public function verificationData($key=[],$data=[],$return=true){
        foreach ($key as $value){
            if(!(isset($data[$value])&&$data[$value])){
                if($return){
                    $this->message = $value.'必须传入';
                    return false;
                }else{
                    throw new \Exception($value.'必须传入');
                }
            }
        }
        return true;
    }

    /**获取信息
     * @return string
     */
    public function getMessage(){
        return $this->message;
    }

    /**
     * @param string $str
     * @param array $config
     * @return false|Basics
     */
    public static function make(string $str='',array $config=[]){
        if(empty($str)){
            return false;
        }
        $dir = __DIR__.DIRECTORY_SEPARATOR.$str.DIRECTORY_SEPARATOR."Basics.php";
        if(!is_file($dir)){
            return false;
        }
//        $obj = app("Maowenke\PersonalWechatSdk\\".$str."\\Basics");
        if($str=='applet'){
            return new WecateApplet($config);
        }elseif ($str='app'){
            return new WecateApp($config);
        }
    }

    /**获取当前用户的ip
     * @return array|false|mixed|string
     */
    protected function getIp(){
        if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))
            $ip = getenv("HTTP_CLIENT_IP");
        else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "unknown"))
            $ip = getenv("HTTP_X_FORWARDED_FOR");
        else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "unknown"))
            $ip = getenv("REMOTE_ADDR");
        else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "unknown"))
            $ip = $_SERVER['REMOTE_ADDR'];
        else
            $ip = "unknown";
        return($ip);
    }

    /**获取签名
     * @param array $data
     * @param string $sign_key
     * @return string
     * @throws \Exception
     */
    protected function getSign($data=[],$sign_key=''){
        $this->verification('mch_key');
        if($sign_key){
            $this->config['mch_key'] = $sign_key;
        }
        if(!$data){
            throw new Exception('签名没有数据');
        }
        $str = $this->ToUrlParams($data);
        $str = $str.'&key='.$this->getCofnig('mch_key');
//        var_dump($str);exit;
        if(strtoupper($this->getCofnig('sign_type')) =='MD5'){
            return strtoupper(md5($str));
        }else{
            return strtoupper(hash_hmac('sha256',$str));
        }
    }
    /**拼接字符串
     * @param $urlObj
     * @return string
     */
    private function ToUrlParams($urlObj)
    {
        ksort($urlObj);
        $buff = "";

        foreach ($urlObj as $k => $v)
        {
            if($k != "sign"){
                if(!empty($v)&&$v){
                    $buff .= $k . "=" . $v . "&";
                }
            }
        }
        $buff = trim($buff, "&");
        return $buff;
    }
    /**将数组转化成xml
     * @param array $array
     * @return bool|string
     */
    public function array_to_xml($array=[]){
        if(!is_array($array) || count($array) <= 0){
            return false;
        }
        $xml = "<xml>";
        foreach ($array as $key=>$val){
            if($key=='sign'){
                $xml.="<".$key.">".$val."</".$key.">";
                continue;
            }
            if (is_numeric($val)){
                $xml.="<".$key.">".$val."</".$key.">";
            }else{
                $xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
            }
        }
        $xml.="</xml>";
        return $xml;
    }
    //解析xml数据
    public function xml($xml){
//        $xml = $this->rulit;
        $xml = simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOCDATA);
        $data  = (array)$xml;
        $this->rult = $data;
        return $data;
    }
    /**获取最后结果
     * @return bool
     */
    public function getrult(){
//        echo '<pre>';
//        print_r($this->rult);
//        exit;
        if(isset($this->rult['return_msg'])&&($this->rult['return_msg']=='ok'||$this->rult['return_msg']=='OK')){
            if($this->config['trade_type']=='APP'){
                $res['appid'] = $this->config['appid'];
                $res['noncestr'] = $this->newdata['nonce_str'];
                $res['package'] = "Sign=WXPay";
                $res['partnerid'] = $this->config['mch_id'];
                $res['prepayid'] = $this->rult['prepay_id'];
                $res['timestamp'] = time();
                $res['sign'] = $this->getSign($res);
                return $res;
            }elseif ($this->config['trade_type']=='JSAPI'){
                $res['appId'] = $this->config['appid'];
                $res['nonceStr'] = $this->newdata['nonce_str'];
                $res['package'] = "prepay_id=".$this->rult['prepay_id'];
//                $res['partnerid'] = $this->config['mch_id'];
//                $res['prepayid'] = $this->rult['prepay_id'];
                $res['timeStamp'] = (string)time();
                $res['signType'] = $this->config['sign_type'];
                $res['paySign'] = $this->getSign($res);
                return $res;
            }elseif($this->config['trade_type']=='MWEB'){
                if(isset($this->rult['return_code'])&&$this->rult['return_code']=='SUCCESS'){
                    return $this->rult;
                }else{
                    $this->message = $this->rult['return_msg']??'';
                    return false;
                }
            }
        }else{
            $this->message = $this->rult['return_msg']??'';
            return false;
        }
    }
}